﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;

namespace Audio
{
    [System.Serializable]
    public class Audio
    {
        public string name;
        public AudioClip clip;
        [Range(0f, 1f)] public float volume = 1f;
        public bool loop = false;
    }

    public class AudioManager : Singleton<AudioManager>
    {
        private AudioSource musicSource;

        [Header("音乐音效列表")]
        [SerializeField] private List<Audio> musicClips = new();
        [SerializeField] private List<Audio> sfxClips = new();

        private Dictionary<string, Audio> musicDict = new();
        private Dictionary<string, Audio> sfxDict = new();

        private ObjectPool<AudioSource> SFXPool;

        private void Awake()
        {
            musicSource = gameObject.AddComponent<AudioSource>();

            // 配置字典映射
            foreach (var audio in musicClips)
                if (audio != null)
                    musicDict[audio.name] = audio;

            foreach (var audio in sfxClips)
                if (audio != null)
                    sfxDict[audio.name] = audio;

            // 配置音效池
            SFXPool = new ObjectPool<AudioSource>(
                createFunc: () =>
                {
                    var go = new GameObject("SFX");
                    go.transform.SetParent(transform);
                    var source = go.AddComponent<AudioSource>();
                    source.playOnAwake = false;
                    return source;
                },
                actionOnGet: (source) =>
                {
                    source.gameObject.SetActive(true);
                },
                actionOnRelease: (source) =>
                {
                    source.Stop();
                    source.clip = null;
                    source.loop = false;
                    source.volume = 1f;
                    source.gameObject.SetActive(false);
                },
                actionOnDestroy: (source) => Destroy(source.gameObject),
                collectionCheck: true,
                defaultCapacity: 10,
                maxSize: 30
            );
        }

        #region 外部接口
        /// <summary>
        /// 管理音乐的播放
        /// </summary>
        /// <param name="clipName">切片名字</param>
        /// <param name="isPlay">是否播放</param>
        public void ManagerMusic(string clipName, bool isPlay)
        {
            if (isPlay)
            {
                if (musicDict.TryGetValue(clipName, out var audio))
                {
                    musicSource.clip = audio.clip;
                    musicSource.loop = audio.loop;
                    musicSource.volume = audio.volume;
                    musicSource.Play();
                }
            }
            else
            {
                // 使用协程淡出音量
                if (musicSource.isPlaying)
                    StartCoroutine(FadeOutAndStopBGM(1f)); // 参数为淡出时间，可调整
            }
        }

        /// <summary>
        /// 管理音效的播放
        /// </summary>
        /// <param name="clipName">切片名字</param>
        /// <param name="volumeScale">音量</param>
        public void PlaySFX(string clipName, float volumeScale = 1f)
        {
            if (sfxDict.TryGetValue(clipName, out var audio))
            {
                var sfxSource = SFXPool.Get();
                sfxSource.clip = audio.clip;
                sfxSource.loop = audio.loop;
                sfxSource.volume = audio.volume * volumeScale;
                sfxSource.Play();
                StartCoroutine(SFXOnEnd(sfxSource));
            }
        }

        public void SetBGMVolume(float volume) => musicSource.volume = volume;

        /// <summary>
        /// 暂停音乐
        /// </summary>
        public void PauseBGM()
        {
            if (musicSource == null) return;
            if (musicSource.isPlaying)
                musicSource.Pause();
            else
                musicSource.UnPause();
        }
        #endregion

        /// <summary>
        /// 用于对象池回收
        /// </summary>
        /// <param name="sfx"></param>
        /// <returns></returns>
        private IEnumerator SFXOnEnd(AudioSource sfx)
        {
            // 等待播放完毕再回收
            yield return new WaitWhile(() => sfx.isPlaying);
            SFXPool.Release(sfx);
        }

        /// <summary>
        /// 淡出并停止BGM
        /// </summary>
        /// <param name="fadeDuration">淡出所需时间（秒）</param>
        private IEnumerator FadeOutAndStopBGM(float fadeDuration)
        {
            float startVolume = musicSource.volume;
            float elapsed = 0f;

            while (elapsed < fadeDuration)
            {
                elapsed += Time.deltaTime;
                musicSource.volume = Mathf.Lerp(startVolume, 0f, elapsed / fadeDuration);
                yield return null;
            }

            musicSource.Stop();
            musicSource.volume = startVolume; // 恢复原始音量，以便下次播放正常
        }
    }
}
